/*
 * PositionValidator.java
 *
 * Created on January 11, 2007, 12:58 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package net.sf.iSnake.core;

import java.util.Iterator;
import java.util.Vector;

/**
 *
 * @author thelinuxmaniac
 * @description
 * This class provides methods to check if a particular position in the game field is valid for an object (like food,snake,etc)
 * It allows to store and modify the the restricted sites in the game field for all the possible object (like food,snake,etc)
 * The check list for objects will grow as the game proceeds to new levels due to addition of difficulty level
 * The order of checking the constrains will be decided by the priority level of each constrain. Failing of one higher level 
 * constrain will result in "INVALID" response and any remaining constrains will not be checked further.
 */
public class PositionValidator {
    
    /**
     * Access the GameArea Object Id using these predefined constants
     *
     * public static final short GAMEAREA_OBJECT_SNAKE  = 1;    // Points in the gamearea where snake CANNOT be placed
     * public static final short GAMEAREA_OBJECT_WALL   = 2;    // Points in the gamearea where wall CANNOT be placed
     * public static final short GAMEAREA_OBJECT_FOOD   = 3;    // Points in gamearea where food CANNOT be placed
     *
     */
    
    public static final short GAMEAREA_OBJECT_SNAKE  = 1;    // Points in the gamearea where snake CANNOT be placed
    public static final short GAMEAREA_OBJECT_WALL   = 2;    // Points in the gamearea where wall CANNOT be placed
    public static final short GAMEAREA_OBJECT_FOOD   = 3;    // Points in gamearea where food CANNOT be placed
    
    private Vector constrainSnake = new Vector(10);
    private Vector constrainWall = new Vector(10);
    private Vector constrainFood =  new Vector(10);
    
    private Vector lastSnakeConstrainVector;
    private Vector lastWallConstrainVector;
    private Vector lastFoodConstrainVector;

    /** Creates a new instance of PositionValidator */
    public PositionValidator() {
    }
    
    /**
     * Adds a GameArea coordinate as a forbidden area for respective gameAreaObject
     * @param gac The coordinate in the GameArea which is to be restricted
     * @param gameAreaObjectId The GameArea Object id (eg: 1 for snake, 2 for wall, 3 for food)
     * @return returns true if the addition of new constrain is successful. returns false otherwise
     */
    public boolean addConstrain(GameAreaCoordinate gac,short gameAreaObjectId)
    {
        switch(gameAreaObjectId)
        {
            case GAMEAREA_OBJECT_SNAKE:
                return constrainSnake.add(gac);
            case GAMEAREA_OBJECT_WALL:
                return constrainWall.add(gac);
            case GAMEAREA_OBJECT_FOOD:
                return constrainFood.add(gac);
            default:
                return false;
        }
    }

    /**
     * Adds a Vector (collection of GameArea coordinate) as a forbidden area for respective gameAreaObject
     * @param constrainAsVector The coordinates (packed as vector) in the GameArea which is to be restricted
     * @param gameAreaObjectId The GameArea Object id (eg: 1 for snake, 2 for wall, 3 for food)
     * @return returns true if the addition of new constrains is successful. returns false otherwise
     */
    public boolean addConstrain(Vector constrainAsVector,short gameAreaObjectId)
    {
        System.out.println("wall constrain sent by IMJ = "+constrainAsVector.toString());
        System.out.println("old wall constrain = "+constrainWall.toString());
        switch(gameAreaObjectId)
        {
            case GAMEAREA_OBJECT_SNAKE:
                constrainSnake = (Vector) constrainAsVector.clone();
                return true;
//                return constrainSnake.addAll(constrainAsVector);

            case GAMEAREA_OBJECT_WALL:
                constrainWall = (Vector) constrainAsVector.clone();
                System.out.println("new wall constrains registering constrain for wall = "+constrainWall.toString());
                return true;
//                return constrainWall.addAll(constrainAsVector);

            case GAMEAREA_OBJECT_FOOD:
                constrainFood = (Vector) constrainAsVector.clone();
                return true;
//                return constrainFood.addAll(constrainAsVector);

            default:
                return false;
        }
    }
    /**
     * Removes a GameArea coordinate from the list of forbidden area for respective gameAreaObject
     * @param gac The coordinate in the GameArea which is to be removed from the restriction list
     * @param gameAreaObjectId The GameArea Object id (eg: 1 for snake, 2 for wall, 3 for food)
     * @return returns true if the removal of new the desired constrain is successful. returns false otherwise
     */
    public boolean removeConstrain(GameAreaCoordinate gac,short gameAreaObjectId)
    {
        switch(gameAreaObjectId)
        {
            case GAMEAREA_OBJECT_SNAKE:
                return constrainSnake.remove(gac);
            case GAMEAREA_OBJECT_WALL:
                return constrainWall.remove(gac);
            case GAMEAREA_OBJECT_FOOD:
                return constrainFood.remove(gac);
            default:
                return false;
        }
        
    }
    /**
     * Removes a Vector (collection of GameArea coordinate) from the list of forbidden area for respective gameAreaObject
     * @param constrainAsVector The coordinates in the GameArea which is to be removed from restriction list
     * @param gameAreaObjectId The GameArea Object id (eg: 1 for snake, 2 for wall, 3 for food)
     * @return returns true if the removal of new constrain is successful. returns false otherwise
     */
    public boolean removeConstrain(Vector constrainAsVector,short gameAreaObjectId)
    {
        switch(gameAreaObjectId)
        {
            case GAMEAREA_OBJECT_SNAKE:
                return constrainSnake.removeAll(constrainAsVector);
            case GAMEAREA_OBJECT_WALL:
                return constrainWall.removeAll(constrainAsVector);
            case GAMEAREA_OBJECT_FOOD:
                return constrainFood.removeAll(constrainAsVector);
            default:
                return false;
        }
        
    }
    /**
     * Removes the Vector (collection of GameArea coordinate) that was last added to the restriction list
     * @param gameAreaObjectId The GameArea Object id (eg: 1 for snake, 2 for wall, 3 for food)
     * @return returns a Vector containing the coordinates that was just removed from the list
     */
    public Vector removeSnakeConstrain(short gameAreaObjectId)
    {
        switch(gameAreaObjectId)
        {
            case GAMEAREA_OBJECT_SNAKE:
                if(constrainSnake.removeAll(lastSnakeConstrainVector) == true)
                    return lastSnakeConstrainVector;
                else
                    return new Vector(0);

            case GAMEAREA_OBJECT_WALL:
                if(constrainWall.removeAll(lastWallConstrainVector) == true)
                    return lastWallConstrainVector;
                else
                    return new Vector(0);

            case GAMEAREA_OBJECT_FOOD:
                if(constrainFood.removeAll(lastFoodConstrainVector) == true)
                    return lastFoodConstrainVector;
                else
                    return new Vector(0);
            default:
                return new Vector(0);
        }
    }
    
    public boolean isSnakePositionValid(GameAreaCoordinate gac)
    {
//        System.out.println("!constrainWall.contains(gac)="+!constrainWall.contains(gac)+" for coordinate "+gac.toString());
        GameAreaCoordinate tempGAC = new GameAreaCoordinate(gac.getX(),gac.getY());
        GameAreaCoordinate t1 = new GameAreaCoordinate(-1,-1);

        //System.out.println("contents of wall constrain ====================================================================================================");
        //System.out.println("wall constrain= "+constrainWall.toString());
        
        for (Iterator itr = constrainWall.iterator();itr.hasNext();)   {
            t1 = (GameAreaCoordinate) itr.next();
            if (t1.equals(tempGAC)) {
                System.out.println("MATCHED hence returning false "+" for coordinate "+gac.toString()+" tempGAC = "+tempGAC.toString()+" t1 = "+t1.toString());
                return false;
                
            }
            else    {
//                System.out.println("NOT MATCHED hence returning false "+" for coordinate "+gac.toString()+" tempGAC = "+tempGAC.toString()+" t1 = "+t1.toString());
            }
        }
        return true;

        
//        return !constrainWall.contains(new GameAreaCoordinate(gac.getX(),gac.getY()));
//        return !constrainWall.contains(gac);
//        return !constrainSnake.contains(gac);
    }
    
    public boolean isWallPositionValid(GameAreaCoordinate gac)
    {
        return !constrainWall.contains(gac);
    }
    
    public boolean isFoodPositionValid(GameAreaCoordinate gac)
    {
        return !constrainFood.contains(gac);
    }

    public Vector getConstrainSnake() {
        return constrainSnake;
    }

    public Vector getConstrainWall() {
        return constrainWall;
    }

    public Vector getConstrainFood() {
        return constrainFood;
    }
}